<script lang="ts" setup>
import { ref, reactive } from "vue";
import { Plus } from "@element-plus/icons-vue";
import {
  type UploadUserFile,
  type UploadRawFile,
  ElMessage,
} from "element-plus";
import * as XLSX from "xlsx";
import type { XLSXJson, FormattedItem } from "./types";
import { SubjectTypeEnum } from "@/enum/question-test/QuestionTestEnum";
import { saveLocalSubjectData } from "@/utils/question-test";

// 设置子组件导出的 defineExpose() 组件类型，父组件使用时设置组件类型 const ExportXlsxRef = ref<ExportXlsxExpose | null>();
export interface ExportXlsxExpose {
  show: (show: boolean) => void;
}

const emits = defineEmits<{
  (e: "onSucess", done: boolean): void;
}>();

// dialog是否可见
const visible = ref<boolean>(false);

const btn = reactive({
  // 按钮加载
  loading: false,
  // 按钮是否禁用,默认禁用
  disabled: false,
});

// 显示弹窗
function show(show: boolean) {
  visible.value = show;
}

/**
 * 上传文件改变时触发
 * @param file 上传的文件
 * @param fileList 上传的文件列表
 */
async function handleChange(uploadFile: UploadUserFile) {
  openLoading(true);
  let file = uploadFile.raw as UploadRawFile;
  if (!file) {
    return ElMessage.error("请选择文件");
  }
  // 读取file中的数据，把文件解析成二进制数据，把二进制数据变为
  let bufferData = await readFile(file);
  if (!bufferData) {
    return ElMessage.error("请选择正确的XLSX文件");
  }
  let workbook: XLSX.WorkBook = XLSX.read(bufferData, { type: "binary" });
  // 拿到第一个sheet表的数据，把第一个表格的数据转换成JSON格式
  let worksheet = workbook.Sheets[workbook.SheetNames[0]];
  // 转换为json数据
  const json: Array<XLSXJson> = XLSX.utils.sheet_to_json(worksheet);
  if (json.length) {
    ElMessage.success("数据格式化完成");
  }
  console.log("转为的json数据==>", json);

  // 格式化答案选项之后的全部数据
  const all = formatAnswers(json);
  if (!all.length) {
    return ElMessage.error("请选择正确的XLSX文件");
  }
  // 保存各种类型的题目数据
  saveQuestionData(all, SubjectTypeEnum.ALL);
  emits("onSucess", true);
  // 数据格式化完成
  openLoading(false);
  show(false);
}

/**
 * 保存各种类型的题目数据
 * @param data 格式化后的题目数据
 */
function saveQuestionData<K extends SubjectTypeEnum>(
  questions: FormattedItem[],
  type?: K
) {
  let data = {
    [SubjectTypeEnum.ALL]: questions,
  };

  // 将数据保存到本地
  for (let key in data) {
    // 如果type传有，就根据type只保存指定的数据
    if (type && key !== type) {
      continue;
    }
    saveLocalSubjectData(key, data[key as keyof typeof data]);
  }
  console.log("最终格式完成的数据==>", data);
}

/**
 * 按照二进制读取excel文件
 * @param file blob文件
 */
function readFile(file: UploadRawFile) {
  return new Promise<string | ArrayBuffer | null | undefined>((resolve) => {
    const reader = new FileReader();
    reader.onload = (e: ProgressEvent<FileReader>) => {
      resolve(e.target?.result);
    };
    reader.readAsBinaryString(file);
  });
}

/**
 * 格式化答案选项
 * @param originalArray 原始数组
 * @returns 格式化后的数组
 */
function formatAnswers(originalArray: XLSXJson[]): FormattedItem[] {
  let data = originalArray.map((item) => {
    const answers = item.topic
      .replace(/([A-D]\.)\s*\n\s*/g, "$1") // 移除选项字母和选项内容之间的换行和多余空格
      .replace(/\s*\n\s*([A-D]\.)/g, "\n$1") // 确保每个选项在新行的开头
      .split(/\r?\n/)
      .filter((line) => line.trim().length > 0)
      .slice(1)
      .map((answer) => ({ title: answer.trim() }));

    if (item.subject == SubjectTypeEnum.JUDGE) {
      const judge = [{ title: "对" }, { title: "错" }];
      item.topic = item.topic.replace(/[对错]）?/g, "").replace(/（/g, "");
      answers.push(...judge);
    }

    return {
      subject: item.subject,
      topic: item.topic.split(/\r?\n/)[0],
      select: item.select,
      answers,
    };
  });
  return data;
}

// 提交表单
const handleSubmit = () => {
  show(false);
};

// 取消
const handleCancel = () => {
  show(false);
};

// 关闭弹窗
const handleClose = (done: () => void) => {
  show(false);
  done();
};

// 是否打开loading
const openLoading = (open: boolean) => {
  btn.loading = open;
  btn.disabled = open;
};

defineExpose({
  show,
});

defineOptions({
  name: "ExportXlsx",
});
</script>

<template>
  <div class="export-xlsx">
    <el-dialog
      top="30vh"
      class="custom-dialog"
      v-model="visible"
      title="上传XLSX文件"
      width="80%"
      destroy-on-close
      :close-on-click-modal="false"
      :before-close="handleClose"
    >
      <el-upload
        action="#"
        accept=".xlsx"
        class="upload-xlsx"
        :multiple="false"
        :auto-upload="false"
        :disabled="btn.disabled"
        :show-file-list="false"
        :on-change="handleChange"
      >
        <el-icon
          v-loading.lock="btn.loading"
          element-loading-text="🥝数据格式中..."
          class="uploader-icon"
          ><Plus
        /></el-icon>
      </el-upload>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="handleCancel">取消</el-button>
          <el-button
            type="primary"
            :loading="btn.loading"
            :disabled="btn.disabled"
            @click="handleSubmit"
          >
            确定
          </el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<style lang="scss" scoped>
.export-xlsx {
  :deep(.upload-xlsx) {
    .el-upload {
      border: 2px dashed var(--el-border-color);
      border-radius: 2px;
      cursor: pointer;
      position: relative;
      overflow: hidden;
      transition: var(--el-transition-duration-fast);
    }

    .el-icon.uploader-icon {
      font-size: 28px;
      color: #8c939d;
      width: 8rem;
      height: 8rem;
      text-align: center;
    }

    .el-upload:hover {
      border-color: var(--el-color-primary);
    }
  }
}
</style>
